home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / SCC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-28  |  45.5 KB  |  1,506 lines

  1. #ifdef MSDOS
  2. /* Generic driver for Z8530 boards, modified from the PE1CHL
  3.  * driver for use with NOS. This version also supports the NRS
  4.  * mode when used as an asynch port. Device setup is similar to
  5.  * that of the PE1CHL version, with the addition of user specification
  6.  * of buffer size (bufsize). See the file "scc.txt" for general
  7.  * information on the use of this driver and setup procedures.
  8.  *
  9.  * General differences between this driver and the original version:
  10.  *
  11.  * 1) Slip encoding and decoding is not done in the driver, but
  12.  *    using the routines in slip.c, and these routines are supported
  13.  *    in a manner similar to the asynch routines for the 8250. The
  14.  *    input is handled via fifo buffer, while output is direct. The
  15.  *    routines scc_send and get_scc are called via pointers in the
  16.  *    Slip and Nrs structs for the parcticular channel.
  17.  *
  18.  * 2) The timer routine, scctim, is not installed directly in the
  19.  *    timer interrupt chain, but is called through the systick routine
  20.  *    in pc.c.
  21.  *
  22.  * 3) Facilities of nos are used whenever possible in place of direct
  23.  *    structure or variable manipulation. Mbuf management is handled
  24.  *    this way, along with interface initialization.
  25.  *
  26.  * 4) Nrs mode support is added in a manner similar to that of the
  27.  *    Slip support. I have not had an opportunity to test this, but
  28.  *    it is essentially identical to the way the 8250 version works.
  29.  *
  30.  * 5) Callsign specification on radio modes (kiss,nrs,ax25) is an
  31.  *    option. If not supplied, the value of Mycall will be used.
  32.  *
  33.  * 6) Bufsize specification is now a parameter on setup of each channel.
  34.  *    This is the size of the fifo on asynch input, and the size of
  35.  *    mbuf buffers for sdlc mode. Since the fifo buffer can fill up,
  36.  *    this value should be reasonably large for asynch mode. Mbufs
  37.  *    are chained when they fill up, so having a small bufsize with
  38.  *    sdlc modes (ax25) does not result in loss of characters.
  39.  *
  40.  * 7) Because slip and nrs decoding is handled outside the driver,
  41.  *    sccstat cannot be used to report sent and receive packet counts
  42.  *    in asynch mode, and these fields are blanked on display in asynch
  43.  *    modes.
  44.  *
  45.  *
  46.  * I am interested in setting up some default initializations for
  47.  * the popular Z8530 boards, to minimize user problems in constructing
  48.  * the proper attach init entries. These would allow for shortened
  49.  * entries to use the defaults, such as "attach scc 1 init drsi" to
  50.  * attach a DRSI board in standard configuration at its default address.
  51.  * Since I do not have complete technical information on all such boards,
  52.  * I would very much appreciate any information that users can provide
  53.  * me regarding particular boards.
  54.  *
  55.  * 1/25/90
  56.  *
  57.  * Modifications:
  58.  *
  59.  * 2/17/90:
  60.  *
  61.  * 1) Added mods from PE1CHL which reflect relevent changes to the
  62.  *    scc driver in his version of net between 10/89 and 1/90. Changes
  63.  *    incorporated include additional delays in sccvec.asm, addition
  64.  *    of external clock mode, and initialization for the 8536 as a
  65.  *    clock divider on the DRSI board. "INLINE" is a slight delay
  66.  *    for register access incorporated for use with the inline i/o
  67.  *    code in MSC. This may not be useful or necessary with TURBO.
  68.  *    Changes making "TPS" a variable were not added, since the
  69.  *    scc timer does not install itself on the hardware interrupt
  70.  *    in this version.
  71.  * 
  72.  *
  73.  * Ken Mitchum, KY3B       km@cs.pitt.edu  km@dsl.pitt.edu
  74.  *                             or mail to the tcpip group
  75.  *
  76.  */
  77.  
  78. /* Added ANSI-style prototypes, reformatted source, minor delinting.
  79.  * Integrated into standard 900201 NOS by KA9Q.
  80.  */
  81.  
  82. /*
  83.  * Generic driver for Z8530 SCC chip in SLIP, KISS or AX.25 mode.
  84.  *
  85.  * Written by R.E. Janssen (PE1CHL) using material from earlier
  86.  * EAGLE and PC100 drivers in this package.
  87.  *
  88.  * The driver has initially been written for my own Atari SCC interface
  89.  * board, but it could eventually replace the other SCC drivers.
  90.  *
  91.  * Unfortunately, there is little consistency between the different interface
  92.  * boards, as to the use of a clock source, the solution for the fullduplex
  93.  * clocking problem, and most important of all: the generation of the INTACK
  94.  * signal.    Most designs do not even support the generation of an INTACK and
  95.  * the read of the interrupt vector provided by the chip.
  96.  * This results in lots of configuration parameters, and a fuzzy
  97.  * polltable to be able to support multiple chips connected at one interrupt
  98.  * line...
  99.  *
  100.  */
  101.  
  102.  
  103. #include "global.h"
  104. #ifdef SCC
  105. #include "ctype.h"
  106. #include <time.h>
  107. #include "mbuf.h"
  108. #include "netuser.h"
  109. #include "iface.h"
  110. #include "pktdrvr.h"
  111. #include "slip.h"
  112. #include "nrs.h"
  113. #include "n8250.h"
  114. #include "scc.h"
  115. #include "z8530.h"
  116. #include "z8536.h"
  117. #include "trace.h"
  118. #include "pc.h"
  119. #include "kiss.h"
  120. #include "devparam.h"
  121.  
  122. #if !defined(_lint)
  123. static char rcsid[] OPTIONAL = "$Id: scc.c,v 1.13 1996/12/29 02:47:22 root Exp root $";
  124. #endif
  125.  
  126. /* interrupt handlers */
  127. extern void sccvec();
  128. extern void sccnovec();
  129.  
  130. /* variables used by the SCC interrupt handler in sccvec.asm */
  131. static void (*Orgivec)();    /* original interrupt vector */
  132.  
  133. struct sccinfo Sccinfo = {0};        /* global info about SCCs */
  134. struct sccchan *Sccchan[2 * MAXSCC] = {0}; /* information per channel */
  135. ioaddr Sccvecloc = {0};            /* location to access for SCC vector */
  136. unsigned char Sccmaxvec = {0};        /* maximum legal vector from SCC */
  137. ioaddr Sccpolltab[MAXSCC+1][2] = {0};    /* polling table when no vectoring */
  138.  
  139. #if defined(INLINE)
  140. static unsigned scc_delay (unsigned v);
  141.  
  142. static unsigned scc_delay (v)        /* delay for about 5 PCLK cycles */
  143.    unsigned v;                /* pass-through used for input */
  144.  
  145. {
  146.    register int i,j;            /* it takes time to save them */
  147.  
  148.    return v;                /* return the passed parameter */
  149. }
  150. #endif
  151.  
  152. unsigned char Random = 0;        /* random number for p-persist */
  153.  
  154. static int scc_call (struct iface *ifp,char *call);
  155. static int scc_init (int nchips,ioaddr iobase,int space,int aoff,
  156.  int boff,int doff,ioaddr intack,int ivec,long clk,int pclk,int hwtype,
  157.  int hwparam);
  158. static int scc_raw (struct iface *ifp,struct mbuf *bp);
  159. static int scc_stop (struct iface *ifp);
  160. static int get_scc (int dev);
  161. static int scc_send (int dev,struct mbuf *bp);
  162. static int scc_async (struct sccchan *scc);
  163.  
  164. static void scc_sdlc (struct sccchan *scc);
  165. static void scc_tossb (struct sccchan *scc);
  166. static void scc_txon (struct sccchan *scc);
  167. static void scc_txoff (struct sccchan *scc);
  168. static int32 scc_aioctl (struct iface *ifp,int cmd,int set,int32 val);
  169. static int32 scc_sioctl (struct iface *ifp,int cmd,int set,int32 val);
  170. static void scc_sstart (struct sccchan *scc);
  171. static unsigned int scc_speed (struct sccchan *scc,
  172.   unsigned int clkmode,long speed);
  173. static void scc_asytx (struct sccchan *scc);
  174. static void scc_asyex (struct sccchan *scc);
  175. static void scc_asyrx (struct sccchan *scc);
  176. static void scc_asysp (struct sccchan *scc);
  177. static void scc_sdlctx (struct sccchan *scc);
  178. static void scc_sdlcex (struct sccchan *scc);
  179. static void scc_sdlcrx (struct sccchan *scc);
  180. static void scc_sdlcsp (struct sccchan *scc);
  181.  
  182. /* Attach an SCC channel to the system, or initialize SCC driver.
  183.  * operation depends on argv[2]:
  184.  * when "init", the SCC driver is initialized, and global information about
  185.  * the hardware is set up.
  186.  * argv[0]: hardware type, must be "scc"
  187.  * argv[1]: number of SCC chips we will support
  188.  * argv[2]: mode, must be: "init" in this case
  189.  * argv[3]: base address of SCC chip #0 (hex)
  190.  * argv[4]: spacing between SCC chip base addresses
  191.  * argv[5]: offset from chip base address to channel A control register
  192.  * argv[6]: offset from chip base address to channel B control register
  193.  * argv[7]: offset from each channel's control register to data register
  194.  * argv[8]: address of INTACK/Read Vector port. 0 to read from RR3A/RR2B
  195.  * argv[9]: CPU interrupt vector number for all connected SCCs
  196.  * argv[10]: clock frequency (PCLK/RTxC) of all SCCs in cycles per second
  197.  *         prefix with "p" for PCLK, "r" for RTxC clock (for baudrate gen)
  198.  * argv[11]: optional hardware type (for special features)
  199.  * argv[12]: optional extra parameter for special hardware
  200.  *
  201.  * otherwise, a single channel is attached using the specified parameters:
  202.  * argv[0]: hardware type, must be "scc"
  203.  * argv[1]: SCC channel number to attach, 0/1 for first chip A/B, 2/3 for 2nd...
  204.  * argv[2]: mode, can be:
  205.  *        "slip", "kiss", "ax25"
  206.  * argv[3]: interface label, e.g., "sl0"
  207.  * argv[4]: maximum transmission unit, bytes
  208.  * argv[5]: interface speed, e.g, "1200". prefix with "d" when an external
  209.  *        divider is available to generate the TX clock.    When the clock
  210.  *        source is PCLK, this can be a /32 divider between TRxC and RTxC.
  211.  *        When the clock is at RTxC, the TX rate must be supplied at TRxC.
  212.  *        This is needed only for AX.25 fullduplex.
  213.  *        When this arg is given as "ext", the transmit and receive clock
  214.  *        are external, and the BRG and DPLL are not used.
  215.  * argv[6]: buffer size
  216.  * argv[7]: callsign used on the radio channels (optional)
  217.  */
  218.  
  219. int
  220. scc_attach(argc,argv)
  221. int argc;
  222. char *argv[];
  223. {
  224.     register struct iface *ifp;
  225.     struct sccchan *scc;
  226.     unsigned int chan,brgrate;
  227.     int pclk = 0,hwtype = 0,hwparam = 0;
  228.     int xdev;
  229.     char *cp;
  230.  
  231.     /* first handle the special "init" mode, to initialize global stuff */
  232.  
  233.     if(!strcmp(argv[2],"init")){
  234.     if(argc < 11)            /* need at least argv[1]..argv[10] */
  235.         return -1;
  236.  
  237.     if(isupper(argv[10][0]))
  238.         argv[10][0] = tolower(argv[10][0]);
  239.  
  240.     if(argv[10][0] == 'p'){    /* wants to use PCLK as clock? */
  241.         pclk = 1;
  242.         argv[10]++;
  243.     } else {
  244.         if(argv[10][0] == 'r')    /* wants to use RTxC? */
  245.         argv[10]++;        /* that's the default */
  246.     }
  247.     if(argc > 11)            /* optional hardware type */
  248.         hwtype = htoi(argv[11]);    /* it is given in hex */
  249.  
  250.     if(argc > 12)            /* optional hardware param */
  251.         hwparam = htoi(argv[12]);    /* also in hex */
  252.  
  253.     return scc_init(atoi(argv[1]),(ioaddr) htol(argv[3]),atoi(argv[4]),
  254.         atoi(argv[5]),atoi(argv[6]),atoi(argv[7]),
  255.         (ioaddr) htol(argv[8]),atoi(argv[9]),
  256.         atol(argv[10]),pclk,hwtype,hwparam);
  257.     }
  258.     /* not "init", so it must be a valid mode to attach a channel */
  259.     if(strcmp(argv[2],"ax25") && strcmp(argv[2],"kiss") &&
  260.      strcmp(argv[2],"slip") && strcmp(argv[2],"nrs")){
  261.         tprintf("Mode %s unknown for SCC\n",argv[2]);
  262.         return -1;
  263.     }
  264.     if(strcmp(argv[2],"slip") == 0 || strcmp(argv[2],"kiss") == 0){
  265.         for(xdev = 0;xdev < SLIP_MAX;xdev++)
  266.             if(Slip[xdev].iface == NULLIF)
  267.                 break;
  268.         if(xdev >= SLIP_MAX){
  269.             tputs("Too many slip devices\n");
  270.             return -1;
  271.         }
  272.     }
  273. #ifdef NRS
  274.     if(strcmp(argv[2],"nrs") == 0){
  275.         for(xdev = 0;xdev < NRS_MAX;xdev++)
  276.             if(Nrs[xdev].iface == NULLIF)
  277.                 break;
  278.  
  279.         if(xdev >= NRS_MAX){
  280.             tputs("Too many nrs devices\n");
  281.             return -1;
  282.         }
  283.     }
  284. #endif
  285.     if(!Sccinfo.init){
  286.         tputs("First init SCC driver\n");
  287.         return -1;
  288.     }
  289.     if((chan = atoi(argv[1])) > Sccinfo.maxchan){
  290.         tprintf("SCC channel %d out of range\n",chan);
  291.         return -1;
  292.     }
  293.     if(Sccchan[chan] != NULLCHAN){
  294.         tprintf("SCC channel %d already attached\n",chan);
  295.         return -1;
  296.     }
  297.     /* create interface structure and fill in details */
  298.     ifp = (struct iface *) callocw(1,sizeof(struct iface));
  299.     cp = mallocw(strlen(argv[3]) + 1);
  300.     strcpy(cp,argv[3]);
  301.     ifp->name = cp;
  302.     ifp->iface_metric = 1;
  303.  
  304.     ifp->mtu = atoi(argv[4]);
  305.     ifp->dev = chan;
  306.     ifp->stop = scc_stop;
  307.  
  308.     scc = (struct sccchan *) callocw(1,sizeof(struct sccchan));
  309.     scc->ctrl = Sccinfo.iobase + (chan / 2) * Sccinfo.space + Sccinfo.off[chan % 2];
  310.     scc->data = scc->ctrl + Sccinfo.doff;
  311.     scc->iface = ifp;
  312.  
  313.     if(isupper(argv[5][0]))
  314.         argv[5][0] = tolower(argv[5][0]);
  315.  
  316.     switch (argv[5][0]) {
  317.     case 'd':                /* fulldup divider installed? */
  318.         scc->fulldup = 1;        /* set appropriate flag */
  319.         argv[5]++;            /* skip the 'd' */
  320.         break;
  321.  
  322.     case 'e':                /* external clocking? */
  323.         scc->extclock = 1;        /* set the flag */
  324.         break;
  325.     }
  326.  
  327.     scc->bufsiz = atoi(argv[6]);
  328.     ifp->addr = Ip_addr; 
  329.     Sccchan[chan] = scc;        /* put addr in table for interrupts */
  330.  
  331.     switch(argv[2][0]){             /* mode already checked above */
  332. #ifdef AX25
  333.     case 'a':    /* AX.25 */
  334.         scc_sdlc(scc);                /* init SCC in SDLC mode */
  335.  
  336.         if (!scc->extclock) {
  337.             brgrate = scc_speed(scc,32,atol(argv[5]));/* init SCC speed */
  338.             scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  339.         }
  340.  
  341.         brgrate = scc_speed(scc,32,atol(argv[5]));/* init SCC speed */
  342.         scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  343.         setencap(ifp,"AX25");
  344.         scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);    /* set the callsign */
  345.             ifp->ioctl = scc_sioctl;
  346.         ifp->raw = scc_raw;
  347.  
  348.         /* default KISS Params */
  349.         scc->a.txdelay = 36*TPS/100;    /* 360 ms */
  350.         scc->a.persist = 25;        /* 10% persistence */
  351.         scc->a.slottime = 16*TPS/100; /* 160 ms */
  352. #if TPS > 67
  353.         scc->a.tailtime = 3*TPS/100;    /* 30 ms */
  354. #else
  355.         scc->a.tailtime = 2;        /* minimal reasonable value */
  356. #endif
  357.         scc->a.fulldup = 0;        /* CSMA */
  358.         scc->a.waittime = 50*TPS/100; /* 500 ms */
  359.         scc->a.maxkeyup = 7;        /* 7 s */
  360.         scc->a.mintime = 3;        /* 3 s */
  361.         scc->a.idletime = 120;    /* 120 s */
  362.         break;
  363.     case 'k':    /* kiss */
  364.         scc_async(scc);                /* init SCC in async mode */
  365.         brgrate = scc_speed(scc,16,atol(argv[5]));
  366.         scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  367.  
  368.         setencap(ifp,"AX25");
  369.         scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);    /* set the callsign */
  370.  
  371.         ifp->ioctl = kiss_ioctl;
  372.         ifp->raw = kiss_raw;
  373.  
  374.         for(xdev = 0;xdev < SLIP_MAX;xdev++){
  375.             if(Slip[xdev].iface == NULLIF)
  376.                 break;
  377.         }
  378.         ifp->xdev = xdev;
  379.         Slip[xdev].iface = ifp;
  380.         Slip[xdev].type = CL_KISS;
  381.         Slip[xdev].send = scc_send;
  382.         Slip[xdev].get = get_scc;
  383.         ifp->rxproc = newproc("ascc rx",256,asy_rx,xdev,NULL,NULL,0);
  384.         break;
  385. #endif
  386. #ifdef SLIP
  387.     case 's':    /* slip */
  388.         scc_async(scc);                /* init SCC in async mode */
  389.         brgrate = scc_speed(scc,16,atol(argv[5]));
  390.         scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  391.         setencap(ifp,"SLIP");
  392.         ifp->ioctl = scc_aioctl;
  393.         ifp->raw = slip_raw;
  394.         for(xdev = 0;xdev < SLIP_MAX;xdev++){
  395.             if(Slip[xdev].iface == NULLIF)
  396.                 break;
  397.         }
  398.         ifp->xdev = xdev;
  399.         Slip[xdev].iface = ifp;
  400.         Slip[xdev].type = CL_SERIAL_LINE;
  401.         Slip[xdev].send = scc_send;
  402.         Slip[xdev].get = get_scc;
  403.         ifp->rxproc = newproc("ascc rx",256,asy_rx,xdev,NULL,NULL,0);
  404.         break;
  405. #endif
  406. #ifdef NRS
  407.     case 'n':    /* nrs */
  408.         scc_async(scc);                /* init SCC in async mode */
  409.         brgrate = scc_speed(scc,16,atol(argv[5]));
  410.         scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  411.         setencap(ifp,"AX25");
  412.         scc_call(ifp,argc > 7 ? argv[7] : (char *) 0);    /* set the callsign */
  413.         ifp->ioctl = scc_aioctl;
  414.         ifp->raw = nrs_raw;
  415.     
  416.         for(xdev = 0;xdev < NRS_MAX;xdev++)
  417.             if(Nrs[xdev].iface == NULLIF)
  418.                 break;
  419.  
  420.         ifp->xdev = xdev;
  421.         Nrs[xdev].iface = ifp;
  422.         Nrs[xdev].send = scc_send;
  423.         Nrs[xdev].get = get_scc;
  424.         ifp->rxproc = newproc("nscc rx",256,nrs_recv,xdev,NULL,NULL,0);
  425.         break;
  426. #endif
  427.     }
  428.     ifp->next = Ifaces;            /* link interface in list */
  429.     Ifaces = ifp;
  430.     return 0;
  431. }
  432.  
  433. /* SCC driver initialisation. called on "attach scc <num> init ..." */
  434. static int
  435. scc_init(nchips,iobase,space,aoff,boff,doff,intack,ivec,clk,pclk,hwtype,hwparam)
  436. int nchips;            /* number of chips */
  437. ioaddr iobase;            /* base of first chip */
  438. int space,aoff,boff,doff;
  439. ioaddr intack;            /* INTACK ioport or 0 for no INTACK */
  440. int ivec;            /* interrupt vector number */
  441. long clk;            /* clock frequency */
  442. int pclk;            /* PCLK or RTxC for clock */
  443. int hwtype;            /* selection of special hardware types */
  444. int hwparam;            /* extra parameter for special hardware */
  445. {
  446.     int chip,chan;
  447.     ioaddr chipbase;
  448.     register ioaddr ctrl;
  449.     int i_state,d;
  450.     int dum = 1;
  451.  
  452. #define z 0
  453.  
  454.     if(Sccinfo.init){
  455.         tputs("SCC driver already initialized - nothing done\n");
  456.         return 1;
  457.     }
  458.     Sccinfo.init = 1;
  459.     Sccinfo.nchips = nchips;
  460.     Sccinfo.maxchan = (2 * nchips) - 1;
  461.     Sccinfo.iobase = iobase;
  462.     Sccinfo.space = space;
  463.     Sccinfo.off[0] = aoff;
  464.     Sccinfo.off[1] = boff;
  465.     Sccinfo.doff = doff;
  466.     Sccinfo.ivec = ivec;
  467.     Sccinfo.clk = clk;
  468.     Sccinfo.pclk = pclk;
  469.     Sccinfo.hwtype = hwtype;
  470.     Sccinfo.hwparam = hwparam;
  471.  
  472.     /* reset and pre-init all chips in the system */
  473.     for(chip = 0; chip < nchips; chip++){
  474.         chipbase = iobase + chip * space;
  475.         ctrl = chipbase + Sccinfo.off[0];
  476.         i_state = disable ();        /* because of 2-step accesses */
  477.         VOID(RDREG(ctrl));        /* make sure pointer is written */
  478.         WRSCC(ctrl,R9,FHWRES);        /* force hardware reset */
  479.         for (d = 0; d < 1000; d++)    /* wait a while to be sure */
  480.             dum *= 10;
  481.         for(chan = 0; chan < 2; chan++){
  482.             ctrl = chipbase + Sccinfo.off[chan];
  483.  
  484.             /* initialize a single channel to no-op */
  485.             VOID(RDREG(ctrl));        /* make sure pointer is written */
  486.             WRSCC(ctrl,R4,z);        /* no mode selected yet */
  487.             WRSCC(ctrl,R1,z);        /* no W/REQ operation */
  488.             WRSCC(ctrl,R2,16 * chip);    /* chip# in upper 4 bits of vector */
  489.             WRSCC(ctrl,R3,z);        /* disable rx */
  490.             WRSCC(ctrl,R5,z);        /* disable tx */
  491.             WRSCC(ctrl,R9,VIS);        /* vector includes status, MIE off */
  492.             Sccpolltab[chip][chan] = ctrl; /* store ctrl addr for polling */
  493.         }
  494.         if(hwtype & HWEAGLE)        /* this is an EAGLE card */
  495.             WRREG(chipbase + 4,0x08);    /* enable interrupt on the board */
  496.  
  497.         if(hwtype & HWPC100)        /* this is a PC100 card */
  498.             WRREG(chipbase,hwparam);    /* set the MODEM mode (22H normally) */
  499.  
  500.         if(hwtype & HWPRIMUS)        /* this is a PRIMUS-PC */
  501.             WRREG(chipbase + 4,hwparam); /* set the MODEM mode (02H normally) */
  502.  
  503.         if (hwtype & HWDRSI) {        /* this is a DRSI PC*Packet card */
  504.             ioaddr z8536 = chipbase + 7; /* point to 8536 master ctrl reg */
  505.  
  506.             /* Initialize 8536 to perform its divide-by-32 function */
  507.             /* This part copied from N6TTO DRSI-driver */
  508.  
  509.             /* Start by forcing chip into known state */
  510.  
  511.             VOID(RDREG(z8536));        /* make sure pointer is written */
  512.             WRSCC(z8536,CIO_MICR,0x01); /* force hardware reset */
  513.  
  514.             for (d = 0; d < 1000; d++)    /* wait a while to be sure */
  515.                 dum *= 10;
  516.  
  517.             WRSCC(z8536,CIO_MICR,0x00); /* Clear reset and start */
  518.  
  519.             /* Wait for chip to come ready */
  520.  
  521.             while (RDSCC(z8536,CIO_MICR) != 0x02)
  522.                 dum *= 10;
  523.  
  524.             WRSCC(z8536,CIO_MICR,0x26); /* NV|CT_VIS|RJA */
  525.             WRSCC(z8536,CIO_MCCR,0xf4); /* PBE|CT1E|CT2E|CT3E|PAE */
  526.  
  527.             WRSCC(z8536,CIO_CTMS1,0xe2);/* Continuous, EOE, ECE, Pulse output */
  528.             WRSCC(z8536,CIO_CTMS2,0xe2);/* Continuous, EOE, ECE, Pulse output */
  529.             
  530.         WRSCC(z8536,CIO_CT1MSB,0x00); /* Load time constant CTC #1 */
  531.             WRSCC(z8536,CIO_CT1LSB,0x10);
  532.             WRSCC(z8536,CIO_CT2MSB,0x00); /* Load time constant CTC #2 */
  533.             WRSCC(z8536,CIO_CT2LSB,0x10);
  534.  
  535.             WRSCC(z8536,CIO_IVR,0x06);
  536.  
  537.             /* Set port direction bits in port A and B             */
  538.             /* Data is input on bits d1 and d5, output on d0 and d4. */
  539.             /* The direction is set by 1 for input and 0 for output  */
  540.  
  541.             WRSCC(z8536,CIO_PDCA,0x22);
  542.             WRSCC(z8536,CIO_PDCB,0x22);
  543.  
  544.             WRSCC(z8536,CIO_CSR1,CIO_GCB|CIO_TCB); /* Start CTC #1 running */
  545.             WRSCC(z8536,CIO_CSR2,CIO_GCB|CIO_TCB); /* Start CTC #2 running */
  546.         }
  547.  
  548.         restore(i_state);
  549.     }
  550.     Sccpolltab[chip][0] = 0;    /* terminate the polling table */
  551.     Sccvecloc = intack;        /* location of INTACK/vector read */
  552.     Sccmaxvec = 16 * nchips;    /* upper limit on valid vector */
  553.     /* save original interrupt vector */
  554.     Orgivec = getirq(ivec);
  555.  
  556.     if(intack){    /* INTACK method selected? */
  557.         /* set interrupt vector to INTACK-generating routine  */
  558.         setirq(ivec,sccvec);
  559.     } else {
  560.         /* set interrupt vector to polling routine */
  561.         setirq(ivec,sccnovec);
  562.     }
  563.     /* enable the interrupt  */
  564.     maskon(ivec);
  565.     return 0;
  566. }
  567.  
  568. /* initialize an SCC channel in asynchronous mode */
  569. static int
  570. scc_async(scc)
  571. register struct sccchan *scc;
  572. {
  573.     int i_state;
  574.     register struct fifo *fp = &(scc->fifo);
  575.     
  576.     if((fp->buf = malloc(scc->bufsiz)) == NULLCHAR){
  577.         tprintf("scc%d: No space for rx buffer\n",scc->iface->dev);
  578.         return -1;
  579.     }
  580.     fp->bufsize = scc->bufsiz;
  581.     fp->wp = fp->rp = fp->buf;
  582.     fp->cnt = 0;
  583.  
  584.     scc->int_transmit = scc_asytx;    /* set interrupt handlers */
  585.     scc->int_extstat = scc_asyex;
  586.     scc->int_receive = scc_asyrx;
  587.     scc->int_special = scc_asysp;
  588.  
  589.     i_state = disable ();
  590.  
  591.     wr(scc,R4,X16CLK|SB1);        /* *16 clock, 1 stopbit, no parity */
  592.     wr(scc,R1,z);            /* no W/REQ operation */
  593.     wr(scc,R3,Rx8);            /* RX 8 bits/char, disabled */
  594.     wr(scc,R5,Tx8|DTR|RTS);        /* TX 8 bits/char, disabled, DTR RTS */
  595.     wr(scc,R9,VIS);            /* vector includes status */
  596.     wr(scc,R10,NRZ|z);            /* select NRZ */
  597.     wr(scc,R11,RCBR|TCBR);        /* clocks are BR generator */
  598.     wr(scc,R14,Sccinfo.pclk? BRSRC:z);    /* brg source = PCLK/RTxC */
  599.     wr(scc,R15,BRKIE);            /* enable BREAK ext/status int */
  600.  
  601.     or(scc,R3,RxENABLE);        /* enable receiver */
  602.     or(scc,R5,TxENAB);            /* enable transmitter */
  603.  
  604.     WRREG(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
  605.     WRREG(scc->ctrl,RES_EXT_INT);    /* must be done twice */
  606.     scc->status = RDREG(scc->ctrl);    /* read initial status */
  607.  
  608.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  609.     or(scc,R9,MIE);            /* master interrupt enable */
  610.  
  611.     restore(i_state);
  612.     return 0;
  613. }
  614.  
  615. /* initialize an SCC channel in SDLC mode */
  616. static void
  617. scc_sdlc(scc)
  618. register struct sccchan *scc;
  619. {
  620.     int i_state;
  621.  
  622.     scc->int_transmit = scc_sdlctx;    /* set interrupt handlers */
  623.     scc->int_extstat = scc_sdlcex;
  624.     scc->int_receive = scc_sdlcrx;
  625.     scc->int_special = scc_sdlcsp;
  626.  
  627.     i_state = disable ();
  628.  
  629.     wr(scc,R4,X1CLK|SDLC);        /* *1 clock, SDLC mode */
  630.     wr(scc,R1,z);            /* no W/REQ operation */
  631.     wr(scc,R3,Rx8|RxCRC_ENAB);    /* RX 8 bits/char, CRC, disabled */
  632.     wr(scc,R5,Tx8|DTR|TxCRC_ENAB);    /* TX 8 bits/char, disabled, DTR */
  633.     wr(scc,R6,z);            /* SDLC address zero (not used) */
  634.     wr(scc,R7,FLAG);        /* SDLC flag value */
  635.     wr(scc,R9,VIS);            /* vector includes status */
  636.     wr(scc,R10,CRCPS|NRZI|ABUNDER);    /* CRC preset 1, select NRZI, ABORT on underrun */
  637.  
  638.     if (scc->extclock){            /* when using external clocks */
  639.         /* RXclk RTxC, TXclk TRxC. */
  640.         wr(scc,R11,RCRTxCP|TCTRxCP);
  641.         wr(scc,R14,z);            /* No BRG options */
  642.         WRSCC(scc->ctrl,R14,DISDPLL|scc->wreg[R14]); /* No DPLL operation */
  643.     } else {
  644.         if(scc->fulldup){        /* when external clock divider */
  645.             if(Sccinfo.pclk){    /* when using PCLK as clock source */
  646.                 /* RXclk DPLL, TXclk RTxC, out=BRG.     external /32 TRxC->RTxC */
  647.                 wr(scc,R11,RCDPLL|TCRTxCP|TRxCOI|TRxCBR);
  648.                 } else {
  649.                     /* RXclk DPLL, TXclk TRxC.    external TX clock to TRxC */
  650.                     wr(scc,R11,RCDPLL|TCTRxCP);
  651.                     }
  652.             } else {            /* only half-duplex operation */
  653.                 /* RXclk DPLL, TXclk BRG. BRG reprogrammed at every TX/RX switch */
  654. #ifdef    notdef    /* KA9Q - for PSK modem */
  655.                 wr(scc,R11,RCDPLL|TCBR);
  656. #else
  657.                 /* DPLL -> Rx clk, DPLL -> Tx CLK, TxCLK -> TRxC pin */
  658.                 wr(scc,R11,RCDPLL|TCDPLL|TRxCOI|TRxCDP);
  659. #endif
  660.             }
  661.         wr(scc,R14,Sccinfo.pclk? BRSRC:z);    /* BRG source = PCLK/RTxC */
  662.         WRSCC(scc->ctrl,R14,SSBR|scc->wreg[R14]); /* DPLL source = BRG */
  663.         WRSCC(scc->ctrl,R14,SNRZI|scc->wreg[R14]); /* DPLL NRZI mode */
  664.     }
  665.     wr(scc,R15,BRKIE|CTSIE|DCDIE);    /* enable ABORT, CTS & DCD interrupts */
  666.  
  667.     if(RDREG(scc->ctrl) & DCD){    /* DCD is now ON */
  668.         if (!scc->extclock)
  669.             WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  670.         or(scc,R3,ENT_HM|RxENABLE);    /* enable the receiver, hunt mode */
  671.     }
  672.     WRREG(scc->ctrl,RES_EXT_INT);    /* reset ext/status interrupts */
  673.     WRREG(scc->ctrl,RES_EXT_INT);    /* must be done twice */
  674.     scc->status = RDREG(scc->ctrl);    /* read initial status */
  675.  
  676.     or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
  677.     or(scc,R9,MIE);            /* master interrupt enable */
  678.  
  679.     restore(i_state);
  680. }
  681.  
  682. /* set SCC channel speed
  683.  * clkmode specifies the division rate (1,16,32) inside the SCC
  684.  * returns the selected brgrate for "real speed" calculation
  685.  */
  686. static unsigned int
  687. scc_speed(scc,clkmode,speed)
  688. register struct sccchan *scc;
  689. unsigned int clkmode;
  690. long speed;                /* the desired baudrate */
  691. {
  692.     unsigned int brgrate;
  693.     long spdclkm;
  694.     int i_state;
  695.  
  696.     /* calculate baudrate generator value */
  697.  
  698.     if ((spdclkm = speed * clkmode) == 0)
  699.     return 65000U;            /* avoid divide-by-zero */
  700.  
  701.     brgrate = (unsigned) ((Sccinfo.clk + spdclkm) / (spdclkm * 2)) - 2;
  702.  
  703.     i_state = disable ();        /* 2-step register accesses... */
  704.  
  705.     cl(scc,R14,BRENABL);        /* disable baudrate generator */
  706.     wr(scc,R12,brgrate);        /* brg rate LOW */
  707.     wr(scc,R13,brgrate >> 8);        /* brg rate HIGH */
  708.     or(scc,R14,BRENABL);        /* enable baudrate generator */
  709.  
  710.     restore(i_state);
  711.     return brgrate;
  712. }
  713.  
  714. /* de-activate SCC channel */
  715. static int
  716. scc_stop(ifp)
  717. struct iface *ifp;
  718. {
  719.     struct sccchan *scc = Sccchan[ifp->dev];
  720.     int i_state;
  721.  
  722.     i_state = disable ();
  723.  
  724.     VOID(RDREG(scc->ctrl));        /* make sure pointer is written */
  725.     wr(scc,R9,(ifp->dev % 2)? CHRB : CHRA); /* reset the channel */
  726.  
  727.     switch(ifp->type){
  728.     case CL_SERIAL_LINE:
  729.     case CL_KISS:
  730.         free(scc->fifo.buf);
  731.     default:
  732.         break;
  733.     }
  734.     free(scc);
  735.     Sccchan[ifp->dev] = NULLCHAN;
  736.     restore(i_state);
  737.     return 0;
  738. }
  739.  
  740. /* de-activate SCC driver on program exit */
  741. void
  742. sccstop()
  743. {
  744.     if(Sccinfo.init){            /* was it initialized? */
  745.         maskoff(Sccinfo.ivec);        /* disable the interrupt */
  746.         setirq(Sccinfo.ivec,Orgivec);    /* restore original interrupt vector */
  747.     }
  748. }
  749.  
  750. /* perform ioctl on SCC (async) channel
  751.  * this is used for SLIP mode only, and will read/set the line speed
  752.  */
  753. static int32
  754. scc_aioctl(ifp,cmd,set,val)
  755. struct iface *ifp;
  756. int cmd;
  757. int set;
  758. int32 val;
  759. {
  760.     struct sccchan *scc;
  761.     unsigned int brgrate;
  762.  
  763.     scc = Sccchan[ifp->dev];
  764.  
  765.     switch(cmd){
  766.     case PARAM_SPEED:
  767.         if(set){
  768.             brgrate = scc_speed(scc,16,val);
  769.             scc->speed = Sccinfo.clk / (32L * (brgrate + 2));
  770.         }
  771.         return scc->speed;
  772.     }
  773.     return 0;
  774. }
  775.  
  776. /* perform ioctl on SCC (sdlc) channel
  777.  * this is used for AX.25 mode only, and will set the "kiss" parameters
  778.  */
  779. static int32
  780. scc_sioctl(ifp,cmd,set,val)
  781. struct iface *ifp;
  782. int cmd;
  783. int set;
  784. int32 val;
  785. {
  786.     struct sccchan *scc;
  787.     int i_state;
  788.     unsigned int brgrate;
  789.     
  790.     scc = Sccchan[ifp->dev];
  791.  
  792.     switch(cmd){
  793.     case PARAM_SPEED:
  794.         if(set){
  795.             if(val == 0)
  796.                 scc->extclock = 1;
  797.             else {
  798.                 brgrate = scc_speed(scc,32,val);/* init SCC speed */
  799.                 scc->speed = Sccinfo.clk / (64L * (brgrate + 2));/* calc real speed */
  800.             }
  801.         }
  802.         return scc->speed;
  803.     case PARAM_TXDELAY:
  804.         if(set)
  805.             scc->a.txdelay = val;
  806.         return scc->a.txdelay;
  807.     case PARAM_PERSIST:
  808.         if(set)
  809.             scc->a.persist = val;
  810.         return scc->a.persist;
  811.     case PARAM_SLOTTIME:
  812.         if(set)
  813.             scc->a.slottime = val;
  814.         return scc->a.slottime;
  815.     case PARAM_TXTAIL:
  816.         if(set)
  817.             scc->a.tailtime = val;
  818.         return scc->a.tailtime;
  819.     case PARAM_FULLDUP:
  820.         if(set)
  821.             scc->a.fulldup = val;
  822.         return scc->a.fulldup;
  823.     case PARAM_WAIT:
  824.         if(set)
  825.             scc->a.waittime = val;
  826.         return scc->a.waittime;
  827.     case PARAM_MAXKEY:
  828.         if(set)
  829.             scc->a.maxkeyup = val;
  830.         return scc->a.maxkeyup;
  831.     case PARAM_MIN:
  832.         if(set)
  833.             scc->a.mintime = val;
  834.         return scc->a.mintime;
  835.     case PARAM_IDLE:
  836.         if(set)
  837.             scc->a.idletime = val;
  838.         return scc->a.idletime;
  839.     case PARAM_DTR:
  840.         if(set){
  841.             if(val)
  842.                 scc->wreg[R5] |= DTR;
  843.             else
  844.                 scc->wreg[R5] &= ~DTR;
  845.  
  846.             i_state = disable ();
  847.             if(scc->a.tstate == IDLE && scc->timercount == 0)
  848.                 scc->timercount = 1;    /* force an update */
  849.             restore(i_state);
  850.         }
  851.         return (scc->wreg[R5] & DTR) ? 1 : 0;
  852.     case PARAM_GROUP:
  853.         if(set)
  854.             scc->group = val;
  855.         return scc->group;
  856.     }
  857.     return -1;
  858. }
  859.  
  860. /* start SCC transmitter when it is idle (SLIP/KISS mode only) */
  861. static void
  862. scc_sstart(scc)
  863. register struct sccchan *scc;
  864. {
  865.     if(scc->tbp != NULLBUF ||    /* busy */
  866.      scc->sndq == NULLBUF)    /* no work */
  867.         return;
  868.  
  869.     scc->tbp = dequeue(&scc->sndq);
  870.     WRREG(scc->data,FR_END);
  871. }
  872.  
  873. /* show SCC status */
  874. int
  875. dosccstat()
  876. {
  877.     register struct sccchan *scc;
  878.     int i;
  879.  
  880.     if(!Sccinfo.init){
  881.         tputs("SCC driver not initialized\n");
  882.         return 0;
  883.     }
  884.     tputs("Ch Iface    Sent   Rcvd   Error Space Overr   Rxints   Txints   Exints   Spints\n");
  885.  
  886.     for(i = 0; i <= Sccinfo.maxchan; i++){
  887.         if((scc = Sccchan[i]) == NULLCHAN)
  888.             continue;
  889.  
  890.         if(scc->int_receive == scc_asyrx)
  891.             tprintf("%2d %-6s  ** asynch ** %7lu %5u %5u %8lu %8lu %8lu %8lu\n",i,scc->iface->name,
  892.                 scc->rxerrs,scc->nospace,scc->rovers,
  893.                 scc->rxints,scc->txints,scc->exints,scc->spints);
  894.         else
  895.             tprintf("%2d %-6s %6lu %6lu %7lu %5u %5u %8lu %8lu %8lu %8lu\n",i,scc->iface->name,
  896.                 scc->enqueued,scc->rxframes,scc->rxerrs,scc->nospace,scc->rovers,
  897.                 scc->rxints,scc->txints,scc->exints,scc->spints);
  898.     }
  899.     return 0;
  900. }
  901.  
  902. /* send raw frame to SCC. used for AX.25 */
  903. static int
  904. scc_raw(ifp,bp)
  905. struct iface *ifp;
  906. struct mbuf *bp;
  907. {
  908.     struct sccchan *scc;
  909.     int i_state;
  910.  
  911.     dump(ifp,IF_TRACE_OUT,CL_AX25,bp);
  912.     ifp->rawsndcnt++;
  913.     ifp->lastsent = secclock();
  914.  
  915.     scc = Sccchan[ifp->dev];
  916.  
  917.     if (scc->tx_inhibit){        /* transmitter inhibit */
  918.         free_p(bp);
  919.         return -1;
  920.     }
  921.  
  922.     enqueue(&scc->sndq,bp);        /* enqueue packet */
  923.     scc->enqueued++;
  924.  
  925.     i_state = disable ();
  926.  
  927.     if(scc->a.tstate == IDLE){    /* when transmitter is idle */
  928.         scc->a.tstate = DEFER;    /* start the key-up sequence */
  929.         scc->a.maxdefer = TPS * scc->a.idletime /
  930.             scc->a.slottime;
  931.         scc->timercount = scc->a.waittime;
  932.     }
  933.     restore(i_state);
  934.     return 0;
  935. }
  936.  
  937. static int
  938. scc_send(dev,bp)
  939. int dev;
  940. struct mbuf *bp;
  941. {
  942.     struct sccchan *scc;
  943.  
  944.     scc = Sccchan[dev];
  945.     enqueue(&scc->sndq,bp);
  946.  
  947.     if(scc->tbp == NULLBUF)
  948.         scc_sstart(scc);
  949.     return(0);
  950. }
  951.  
  952. /* initialize interface for AX.25 use */
  953. static int
  954. scc_call(ifp,call)
  955. register struct iface *ifp;
  956. char *call;
  957. {
  958.     char out[AXALEN];
  959.  
  960.     ifp->hwaddr = mallocw(AXALEN);
  961.     ifp->ipcall = mallocw(AXALEN);
  962.     if(setcall(out,call) == 0)    {
  963.         memcpy(ifp->hwaddr,out,AXALEN);
  964.         memcpy(ifp->ipcall,out,AXALEN);
  965.     } else    {
  966.         memcpy(ifp->hwaddr,Mycall,AXALEN);
  967.         memcpy(ifp->ipcall,Mycall,AXALEN);
  968.     }
  969.     return 0;
  970. }
  971.  
  972. /* Interrupt handlers for asynchronous modes (kiss, slip) */
  973.  
  974. /* Transmitter interrupt handler */
  975. /* This routine sends data from mbufs in SLIP format */
  976. static void
  977. scc_asytx(scc)
  978. register struct sccchan *scc;
  979. {
  980.     register struct mbuf *bp;
  981.  
  982.     scc->txints++;
  983.  
  984.     if(scc->txchar != 0){        /* a character pending for transmit? */
  985.         WRREG(scc->data,scc->txchar);    /* send it now */
  986.         scc->txchar = 0;        /* next time, ignore it */
  987.         return;
  988.     }
  989.  
  990.     if(scc->tbp == NULLBUF){    /* nothing to send? */
  991.         if((scc->tbp = scc->sndq) != NULLBUF){ /* dequeue next frame */
  992.             scc->sndq = scc->sndq->anext;
  993.             WRREG(scc->data,FR_END);    /* send FR_END to flush line garbage */
  994.         } else {
  995.             WRREG(scc->ctrl,RES_Tx_P);    /* else only reset pending int */
  996.         }
  997.         return;
  998.     }
  999.     while ((bp = scc->tbp)->cnt == 0){ /* nothing left in this mbuf? */
  1000.         bp = bp->next;            /* save link to next */
  1001.  
  1002.         free_mbuf(scc->tbp);
  1003.  
  1004.         if((scc->tbp = bp) == NULLBUF){ /* see if more mbufs follow */
  1005.             WRREG(scc->data,FR_END);    /* frame complete, send FR_END */
  1006.             return;
  1007.         }
  1008.     }
  1009.     /* now bp = scc->tbp (either from while or from if stmt above) */
  1010.  
  1011.     WRREG(scc->data,*(bp->data));    /* just send the character */
  1012.     bp->cnt--;                /* decrease mbuf byte count */
  1013.     bp->data++;                /* and increment the data pointer */
  1014. }
  1015.  
  1016. /* External/Status interrupt handler */
  1017. static void
  1018. scc_asyex(scc)
  1019. register struct sccchan *scc;
  1020. {
  1021.     register unsigned char status,changes;
  1022.  
  1023.     scc->exints++;
  1024.     status = RDREG(scc->ctrl);
  1025.     changes = status ^ scc->status;
  1026.  
  1027.     if(changes & BRK_ABRT){        /* BREAK? */
  1028.         if((status & BRK_ABRT) == 0)    /* BREAK now over? */
  1029.             VOID(RDREG(scc->data));    /* read the NUL character */
  1030.     }
  1031.     scc->status = status;
  1032.     WRREG(scc->ctrl,RES_EXT_INT);
  1033. }
  1034.  
  1035. /* Receiver interrupt handler under NOS.
  1036.  * Since the higher serial protocol routines are all written to work
  1037.  * well with the routines in 8250.c, it makes sense to handle
  1038.  * asynch i/o with the 8530 in a similar manner. Therefore, these
  1039.  * routines are as close to their counterparts in 8250.c as possible.
  1040.  */
  1041.  
  1042. static void
  1043. scc_asyrx(scc)
  1044. register struct sccchan *scc;
  1045. {
  1046.     register struct fifo *fp;
  1047.     char c;
  1048.  
  1049.     scc->rxints++;
  1050.  
  1051.     fp = &(scc->fifo);
  1052.     do {
  1053.         c = RDREG(scc->data);
  1054.         if(fp->cnt != fp->bufsize){
  1055.             *fp->wp++ = c;
  1056.             if(fp->wp >= &fp->buf[fp->bufsize])
  1057.                 fp->wp = fp->buf;
  1058.             fp->cnt++;
  1059.         } else
  1060.             scc->nospace++;
  1061.     } while(RDREG(scc->ctrl) & Rx_CH_AV);
  1062.     ksignal(fp,1);    /* eventually move this to timer routine */
  1063. }
  1064.  
  1065. /* Blocking read from asynch input.
  1066.  * Essentially the same as get_asy() in 8250.c
  1067.  * See comments in asy_rxint().
  1068.  */
  1069. static int
  1070. get_scc(dev)
  1071. int dev;
  1072. {
  1073.     char i_state;
  1074.     register struct fifo *fp;
  1075.     char c;
  1076.  
  1077.     fp = &(Sccchan[dev]->fifo);
  1078.  
  1079.     i_state = disable ();
  1080.     while(fp->cnt == 0)
  1081.         kwait(fp);
  1082.     fp->cnt--;
  1083.     restore(i_state);
  1084.  
  1085.     c = *fp->rp++;
  1086.     if(fp->rp >= &fp->buf[fp->bufsize])
  1087.         fp->rp = fp->buf;
  1088.  
  1089.     return uchar(c);
  1090. }
  1091.  
  1092. int
  1093. scc_frameup(dev)
  1094. int dev;
  1095. {
  1096.     Sccchan[dev]->rxframes++;
  1097.     return 0;
  1098. }
  1099.  
  1100. /* Receive Special Condition interrupt handler */
  1101. static void
  1102. scc_asysp(scc)
  1103. register struct sccchan *scc;
  1104. {
  1105.     register unsigned char status;
  1106.  
  1107.     scc->spints++;
  1108.  
  1109.     status = rd(scc,R1);        /* read receiver status */
  1110.     VOID(RDREG(scc->data));        /* flush offending character */
  1111.  
  1112.     if(status & (CRC_ERR | Rx_OVR))        /* did a framing error or overrun occur ? */
  1113.         scc->rovers++;            /* report as overrun */
  1114.  
  1115.     WRREG(scc->ctrl,ERR_RES);
  1116. }
  1117.  
  1118. /* Interrupt handlers for sdlc mode (AX.25) */
  1119.  
  1120. /* Transmitter interrupt handler */
  1121. static void
  1122. scc_sdlctx(scc)
  1123. register struct sccchan *scc;
  1124. {
  1125.     register struct mbuf *bp;
  1126.  
  1127.     scc->txints++;
  1128.  
  1129.     switch(scc->a.tstate){        /* look at transmitter state */
  1130.     case ACTIVE:            /* busy sending data bytes */
  1131.         while ((bp = scc->tbp)->cnt == 0){    /* nothing left in this mbuf? */
  1132.             bp = bp->next;            /* save link to next */
  1133.             free_mbuf(scc->tbp);    /*KM*/
  1134.             if((scc->tbp = bp) == NULLBUF){/* see if more mbufs follow */
  1135.                 if(RDREG(scc->ctrl) & TxEOM){    /* check tx underrun status */
  1136.                     scc->rovers++;        /* oops, an underrun! count them */
  1137.                     WRREG(scc->ctrl,SEND_ABORT);/* send an abort to be sure */
  1138.                     scc->a.tstate = TAIL;    /* key down tx after TAILTIME */
  1139.                     scc->timercount = scc->a.tailtime;
  1140.                     return;
  1141.                 }
  1142.                 cl(scc,R10,ABUNDER);        /* frame complete, allow CRC transmit */
  1143.                 scc->a.tstate = FLUSH;
  1144.                 WRREG(scc->ctrl,RES_Tx_P);    /* reset pending int */
  1145.                 return;
  1146.             }
  1147.         }
  1148.         /* now bp = scc->tbp (either from while or from if stmt above) */
  1149.         WRREG(scc->data,*(bp->data++)); /* send the character */
  1150.         bp->cnt--;            /* decrease mbuf byte count */
  1151.         return;
  1152.     case FLUSH:    /* CRC just went out, more to send? */
  1153.         or(scc,R10,ABUNDER);        /* re-install underrun protection */
  1154.         /* verify that we are not exeeding max tx time (if defined) */
  1155.         if((scc->timercount != 0 || scc->a.maxkeyup == 0) &&
  1156.          (scc->tbp = scc->sndq) != NULLBUF){ /* dequeue a frame */
  1157.             scc->sndq = scc->sndq->anext;
  1158.             WRREG(scc->ctrl,RES_Tx_CRC); /* reset the TX CRC generator */
  1159.             scc->a.tstate = ACTIVE;
  1160.             scc_sdlctx(scc);        /* write 1st byte */
  1161.             WRREG(scc->ctrl,RES_EOM_L); /* reset the EOM latch */
  1162.             return;
  1163.         }
  1164.         scc->a.tstate = TAIL;        /* no more, key down tx after TAILTIME */
  1165.         scc->timercount = scc->a.tailtime;
  1166.         WRREG(scc->ctrl,RES_Tx_P);
  1167.         return;
  1168.     default:                /* another state */
  1169.         WRREG(scc->ctrl,RES_Tx_P);    /* then don't send anything */
  1170.         return;
  1171.     }
  1172. }
  1173.  
  1174. /* External/Status interrupt handler */
  1175. static void
  1176. scc_sdlcex(scc)
  1177. register struct sccchan *scc;
  1178. {
  1179.     register unsigned char status,changes;
  1180.  
  1181.     scc->exints++;
  1182.     status = RDREG(scc->ctrl);
  1183.     changes = status ^ scc->status;
  1184.  
  1185.     if(changes & BRK_ABRT){        /* Received an ABORT */
  1186.         if(status & BRK_ABRT){        /* is this the beginning? */
  1187.             if(scc->rbp != NULLBUF){/* did we receive something? */
  1188.                 /* check if a significant amount of data came in */
  1189.                 /* this is because the drop of DCD tends to generate an ABORT */
  1190.                 if(scc->rbp->next != NULLBUF || scc->rbp->cnt > sizeof(struct phdr))
  1191.                 scc->rxerrs++;    /* then count it as an error */
  1192.                 scc_tossb(scc);        /* throw away buffer */
  1193.             }
  1194.             VOID(RDREG(scc->data));    /* flush the FIFO */
  1195.             VOID(RDREG(scc->data));
  1196.             VOID(RDREG(scc->data));
  1197.         }
  1198.     }
  1199.     if(changes & CTS){            /* CTS input changed state */
  1200.         if(status & CTS){        /* CTS is now ON */
  1201.             if(scc->a.tstate == KEYWT &&
  1202.                 scc->a.txdelay == 0) /* zero TXDELAY = wait for CTS */
  1203.             scc->timercount = 1;    /* it will start within 10 ms */
  1204.         }
  1205.     }
  1206.     if(changes & DCD){            /* DCD input changed state */
  1207.         if(status & DCD){        /* DCD is now ON */
  1208.             if (!scc->extclock)
  1209.                 WRSCC(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
  1210.             or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
  1211.         } else {            /* DCD is now OFF */
  1212.             cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
  1213.             VOID(RDREG(scc->data));    /* flush the FIFO */
  1214.             VOID(RDREG(scc->data));
  1215.             VOID(RDREG(scc->data));
  1216.             if(scc->rbp != NULLBUF){/* did we receive something? */
  1217.                 /* check if a significant amount of data came in */
  1218.                 /* this is because some characters precede the drop of DCD */
  1219.                 if(scc->rbp->next != NULLBUF || scc->rbp->cnt > sizeof(struct phdr))
  1220.                 scc->rxerrs++;    /* then count it as an error */
  1221.                 scc_tossb(scc);        /* throw away buffer */
  1222.             }
  1223.         }
  1224.     }
  1225.     scc->status = status;
  1226.     WRREG(scc->ctrl,RES_EXT_INT);
  1227. }
  1228.  
  1229. /* Receiver interrupt handler */
  1230. static void
  1231. scc_sdlcrx(scc)
  1232. register struct sccchan *scc;
  1233. {
  1234.     register struct mbuf *bp;
  1235.  
  1236.     scc->rxints++;
  1237.  
  1238.     if((bp = scc->rbp1) == NULLBUF){ /* no buffer available now */
  1239.         if(scc->rbp == NULLBUF){
  1240.             if((bp = alloc_mbuf(scc->bufsiz+sizeof(struct phdr))) != NULLBUF){
  1241.                 scc->rbp = scc->rbp1 = bp;
  1242.                 bp->cnt = sizeof(struct phdr);    /* get past the header */
  1243.             }
  1244.         } else if((bp = alloc_mbuf(scc->bufsiz)) != NULLBUF){
  1245.             scc->rbp1 = bp;
  1246.             for(bp = scc->rbp; bp->next != NULLBUF; bp = bp->next);
  1247.             bp->next = scc->rbp1;
  1248.             bp = scc->rbp1;
  1249.         }
  1250.         if(bp == NULLBUF){
  1251.             VOID(RDREG(scc->data));    /* so we have to discard the char */
  1252.             or(scc,R3,ENT_HM);        /* enter hunt mode for next flag */
  1253.             scc_tossb(scc);        /* put buffers back on pool */
  1254.             scc->nospace++;        /* count these events */
  1255.             return;
  1256.         }
  1257.     }
  1258.  
  1259.     /* now, we have a buffer (at bp). read character and store it */
  1260.     bp->data[bp->cnt++] = RDREG(scc->data);
  1261.  
  1262.     if(bp->cnt == bp->size)        /* buffer full? */
  1263.         scc->rbp1 = NULLBUF;    /* acquire a new one next time */
  1264. }
  1265.  
  1266. /* Receive Special Condition interrupt handler */
  1267. static void
  1268. scc_sdlcsp(scc)
  1269. register struct sccchan *scc;
  1270. {
  1271.     register unsigned char status;
  1272.     register struct mbuf *bp;
  1273.     struct phdr phdr;
  1274.  
  1275.     scc->spints++;
  1276.  
  1277.     status = rd(scc,R1);        /* read receiver status */
  1278.     VOID(RDREG(scc->data));        /* flush offending character */
  1279.  
  1280.     if(status & Rx_OVR){        /* receiver overrun */
  1281.         scc->rovers++;            /* count them */
  1282.         or(scc,R3,ENT_HM);        /* enter hunt mode for next flag */
  1283.         scc_tossb(scc);            /* rewind the buffer and toss */
  1284.     }
  1285.     if(status & END_FR &&        /* end of frame */
  1286.     scc->rbp != NULLBUF){    /* at least received something */
  1287.         if((status & CRC_ERR) == 0 &&    /* no CRC error is indicated */
  1288.         (status & 0xe) == RES8 &&    /* 8 bits in last byte */
  1289.         scc->rbp->cnt > sizeof(phdr)){
  1290.  
  1291.             /* we seem to have a good frame. but the last byte received */
  1292.             /* from rx interrupt is in fact a CRC byte, so discard it */
  1293.             if(scc->rbp1 != NULLBUF){
  1294.                 scc->rbp1->cnt--;    /* current mbuf was not full */
  1295.             } else {
  1296.                 for(bp = scc->rbp; bp->next != NULLBUF; bp = bp->next);
  1297.                     /* find last mbuf */
  1298.  
  1299.                 bp->cnt--;        /* last byte is first CRC byte */
  1300.             }
  1301.  
  1302.             phdr.iface = scc->iface;
  1303.             phdr.type = CL_AX25;
  1304.             memcpy(&scc->rbp->data[0],(char *)&phdr,sizeof(phdr));
  1305.             enqueue(&Hopper,scc->rbp);
  1306.  
  1307.             scc->rbp = scc->rbp1 = NULLBUF;
  1308.             scc->rxframes++;
  1309.         } else {            /* a bad frame */
  1310.             scc_tossb(scc);        /* throw away frame */
  1311.             scc->rxerrs++;
  1312.         }
  1313.     }
  1314.     WRREG(scc->ctrl,ERR_RES);
  1315. }
  1316.  
  1317. /* Throw away receive mbuf(s) when an error occurred */
  1318. static void
  1319. scc_tossb (scc)
  1320. register struct sccchan *scc;
  1321. {
  1322.     register struct mbuf *bp;
  1323.     
  1324.     if((bp = scc->rbp) != NULLBUF){
  1325.         free_p(bp->next);
  1326.         free_p(bp->dup);    /* Should be NULLBUF */
  1327.         bp->next = NULLBUF;
  1328.         scc->rbp1 = bp;        /* Don't throw this one away */
  1329.         bp->cnt = sizeof(struct phdr);    /* Simply rewind it */
  1330.     }
  1331. }
  1332.  
  1333. /* Switch the SCC to "transmit" mode */
  1334. /* Only to be called from an interrupt handler, while in AX.25 mode */
  1335. static void
  1336. scc_txon(scc)
  1337. register struct sccchan *scc;
  1338. {
  1339.     if (!scc->fulldup && !scc->extclock){ /* no fulldup divider? */
  1340.         cl(scc,R3,RxENABLE);        /* then switch off receiver */
  1341.         cl(scc,R5,TxENAB);        /* transmitter off during switch */
  1342.         scc_speed(scc,1,scc->speed);    /* reprogram baudrate generator */
  1343.     }
  1344.     or(scc,R5,RTS|TxENAB);        /* set the RTS line and enable TX */
  1345.     if(Sccinfo.hwtype & HWPRIMUS)    /* PRIMUS has another PTT bit... */
  1346.         WRREG(scc->ctrl + 4,Sccinfo.hwparam | 0x80); /* set that bit! */
  1347. }
  1348.  
  1349. /* Switch the SCC to "receive" mode (or: switch off transmitter)
  1350.  * Only to be called from an interrupt handler, while in AX.25 mode
  1351.  */
  1352. static void
  1353. scc_txoff(scc)
  1354. register struct sccchan *scc;
  1355. {
  1356.     cl(scc,R5,RTS);            /* turn off RTS line */
  1357.     if(Sccinfo.hwtype & HWPRIMUS)    /* PRIMUS has another PTT bit... */
  1358.         WRREG(scc->ctrl + 4,Sccinfo.hwparam); /* clear that bit! */
  1359.  
  1360.     if (!scc->fulldup && !scc->extclock){ /* no fulldup divider? */
  1361.         cl(scc,R5,TxENAB);        /* then disable the transmitter */
  1362.         scc_speed(scc,32,scc->speed);    /* back to receiver baudrate */
  1363.     }
  1364. }
  1365.  
  1366. /* SCC timer interrupt handler. Will be called every 1/TPS s by the 
  1367.  * routine systick in pc.c
  1368.  */
  1369. void scctimer()
  1370. {
  1371.     register struct sccchan *scc;
  1372.     register struct sccchan **sccp;
  1373.     char i_state;
  1374.  
  1375.     i_state = disable ();
  1376.     for(sccp = Sccchan + Sccinfo.maxchan; sccp >= Sccchan; sccp--){
  1377.         if((scc = *sccp) != NULLCHAN &&
  1378.           scc->timercount != 0 &&
  1379.           --(scc->timercount) == 0){
  1380.             /* handle an SCC timer event for this SCC channel
  1381.              * this can only happen when the channel is AX.25 type
  1382.              * (the SLIP/KISS driver does not use timers)
  1383.              */
  1384.             switch(scc->a.tstate){
  1385.             case IDLE:            /* it was idle, this is FULLDUP2 timeout */
  1386.                 scc_txoff(scc);        /* switch-off the transmitter */
  1387.                 break;
  1388.             case DEFER:            /* trying to get the channel */
  1389.                 /* operation is as follows:
  1390.                  * CSMA: when channel clear AND persistence randomgenerator
  1391.                  *     wins, AND group restrictions allow it:
  1392.                  *        keyup the transmitter
  1393.                  *     if not, delay one SLOTTIME and try again
  1394.                  * FULL: always keyup the transmitter
  1395.                  */
  1396.                 if(scc->a.fulldup == 0){
  1397.                     Random = 21 * Random + 53;
  1398.                     if(scc->status & DCD || scc->a.persist < Random){
  1399.                         /* defer transmission again. check for limit */
  1400. defer_it:                    if(--(scc->a.maxdefer) == 0){
  1401.                             /* deferred too long. choice is to:
  1402.                              * - throw away pending frames, or
  1403.                              * - smash-on the transmitter and send them.
  1404.                              * the first would be the choice in a clean
  1405.                              * environment, but in the amateur radio world
  1406.                              * a distant faulty station could tie us up
  1407.                              * forever, so the second may be better...
  1408.                             */
  1409. #ifdef THROW_AWAY_AFTER_DEFER_TIMEOUT
  1410.                             struct mbuf *bp,*bp1;
  1411.  
  1412.                             while ((bp = scc->sndq) != NULLBUF){
  1413.                                 scc->sndq = scc->sndq->anext;
  1414.                                 free_p(bp);
  1415.                             }
  1416. #else
  1417.                             goto keyup; /* just keyup the transmitter... */
  1418. #endif
  1419.                         }
  1420.                         scc->timercount = scc->a.slottime;
  1421.                         break;
  1422.                     }
  1423.                     if(uchar(scc->group) != NOGROUP){
  1424.                         int i;
  1425.                         struct sccchan *scc2;
  1426.  
  1427.                         for(i = 0; i <= Sccinfo.maxchan; i++)
  1428.                             if((scc2 = Sccchan[i]) != NULLCHAN &&
  1429.                              scc2 != scc &&
  1430.                              uchar(scc2->group) & uchar(scc->group) &&
  1431.                              ((scc->group & TXGROUP && scc2->wreg[R5] & RTS) ||
  1432.                              (scc->group & RXGROUP && scc2->status & DCD))){
  1433.                                 goto defer_it;
  1434.                             }
  1435.                     }
  1436.                 }
  1437.             case KEYUP:            /* keyup transmitter (note fallthrough) */
  1438. keyup:                if((scc->wreg[R5] & RTS) == 0){ /* when not yet keyed */
  1439.                     scc->a.tstate = KEYWT;
  1440.                     scc->timercount = scc->a.txdelay; /* 0 if CTSwait */
  1441.                     scc_txon(scc);
  1442.                     break;
  1443.                 }
  1444.                 /* when already keyed, directly fall through */
  1445.             case KEYWT:            /* waited for CTS or TXDELAY */
  1446.                 /* when a frame is available (it should be...):
  1447.                  * - dequeue it from the send queue
  1448.                  * - reset the transmitter CRC generator
  1449.                  * - set a timeout on transmission length, if defined
  1450.                  * - send the first byte of the frame
  1451.                  * - reset the EOM latch
  1452.                  * when no frame available, proceed to TAIL handling
  1453.                  */
  1454.                 if((scc->tbp = scc->sndq) != NULLBUF){
  1455.                     scc->sndq = scc->sndq->anext;
  1456.                     WRREG(scc->ctrl,RES_Tx_CRC);
  1457.                     scc->a.tstate = ACTIVE;
  1458.                     scc->timercount = TPS * scc->a.maxkeyup;
  1459.                     scc_sdlctx(scc);
  1460.                     WRREG(scc->ctrl,RES_EOM_L);
  1461.                     break;
  1462.                 }
  1463.                 /* when no frame queued, fall through to TAIL case */
  1464.             case TAIL:            /* at end of frame */
  1465.                 /* when fulldup is 0 or 1, switch off the transmitter.
  1466.                  * when frames are still queued (because of transmit time limit),
  1467.                  * restart the procedure to get the channel after MINTIME.
  1468.                  * when fulldup is 2, the transmitter remains keyed and we
  1469.                  * continue sending.    IDLETIME is an idle timeout in this case.
  1470.                  */    
  1471.                 if(scc->a.fulldup < 2){
  1472.                     scc->a.tstate = IDLE;
  1473.                     scc_txoff(scc);
  1474.  
  1475.                     if(scc->sndq != NULLBUF){
  1476.                         scc->a.tstate = DEFER;
  1477.                         scc->a.maxdefer = TPS * scc->a.idletime /
  1478.                          scc->a.slottime;
  1479.                         scc->timercount = TPS * scc->a.mintime;
  1480.                     }
  1481.                     break;
  1482.                 }
  1483.                 if(scc->sndq != NULLBUF){ /* still frames on the queue? */
  1484.                     scc->a.tstate = KEYWT; /* continue sending */
  1485.                     scc->timercount = TPS * scc->a.mintime; /* after mintime */
  1486.                 } else {
  1487.                     scc->a.tstate = IDLE;
  1488.                     scc->timercount = TPS * scc->a.idletime;
  1489.                 }
  1490.                 break;
  1491.             case ACTIVE:    /* max keyup time expired */
  1492.             case FLUSH:    /* same while in flush mode */
  1493.                 break;    /* no action required yet */
  1494.             default:            /* unexpected state */
  1495.                 scc->a.tstate = IDLE; /* that should not happen, but... */
  1496.                 scc_txoff(scc);        /* at least stop the transmitter */
  1497.                 break;
  1498.             }
  1499.         }
  1500.     }
  1501.     restore(i_state);
  1502. }
  1503. #endif /* SCC */
  1504. #endif /* MSDOS */
  1505.  
  1506.